
#include "RSAKeyPairGenerator.h"

/** Internal function to generate an RSA key pair with the given
 * number of bits and name.
 * 
 * @param nbits
 * Number of bits desired in the key the be created.
 * 
 * @param name
 * Name of the keys created.
 * 
 * @return
 * Zero on success, 1 on key mismatch, -1 on generation error. */
int RSAKeyPairGenerator::generateKeyPair(int nbits, const char *name)
{
   RSA *rkey = RSA_generate_key(nbits, 0x10001, NULL, NULL);
   if (!rkey) { fSSLCheckError(); return -1; }
   pub = new RSAPublicKey(rkey, name);
   prv = new RSAPrivateKey(rkey, name);
   return (checkAreKeyPair()) ? 0 : 1;
}

/** Generate an RSA key pair with the given number of bits and name.
 * 
 * @param nbits
 * Number of bits desired in the key the be created.
 * 
 * @param name
 * Name of the keys created. */
RSAKeyPairGenerator::RSAKeyPairGenerator(int nbits, const char *name)
{
   generateKeyPair(nbits, name);
}

/** Destructor of the generator. Keys should be popped via popPrivateKey
 * and popPublicKey or they will be destroyed with the generator. */
RSAKeyPairGenerator::~RSAKeyPairGenerator()
{
   if (pub) delete pub;
   pub = NULL;
   if (prv) delete prv;
   prv = NULL;
}

/** Check to see if the internally stored keys make a valid matching key pair.
 * 
 * @return
 * 1 if the keys make a matching pair, zero if they do not, -1 on error. */
int RSAKeyPairGenerator::checkAreKeyPair()
{
   if (!prv)
   {
      errprint("RSA private key has been popped!");
      return -1;
   }
   if (!pub)
   {
      errprint("RSA public key has been popped!");
      return -1;
   }
   return checkAreKeyPair(pub, prv);
}

/** Check to see if these keys make a valid matching key pair.
 * 
 * @param ipub
 * An RSAPublicKey to test.
 * 
 * @param iprv
 * An RSAPrivateKey to test.
 * 
 * @return
 * 1 if the keys make a matching pair, zero if they do not, -1 on error. */
int RSAKeyPairGenerator::checkAreKeyPair(RSAPublicKey *ipub, RSAPrivateKey *iprv)
{
   if (!iprv)
   {
      errprint("RSA private key has been popped!");
      return -1;
   }
   if (!ipub)
   {
      errprint("RSA public key has been popped!");
      return -1;
   }
   return iprv->compareKeyBelongs(ipub);
}

/** Get the public key, but do not remove it from the key pair storage. If
 * it is not removed, it will be deleted along with this class.
 * 
 * @return
 * A pointer to the internally stored RSAPublicKey of the generated pair. */
RSAPublicKey *RSAKeyPairGenerator::getPublicKey()
{
   return pub;
}

/** Get the private key, but do not remove it from the key pair storage. If
 * it is not removed, it will be deleted along with this class.
 * 
 * @return
 * A pointer to the internally stored RSAPrivateKey of the generated pair. */
RSAPrivateKey *RSAKeyPairGenerator::getPrivateKey()
{
   return prv;
}

/** Get the public key, but remove it from the key pair storage, so it is not
 * deleted and freed along with this class.
 * 
 * @return
 * A pointer to the RSAPublicKey of the generated pair. By calling this, the
 * key is removed from this generator instance, and the responsibility to
 * delete the key now rests with the caller. Subsequent calls will return
 * NULL. */
RSAPublicKey *RSAKeyPairGenerator::popPublicKey()
{
   RSAPublicKey *pub_k = pub;
   pub = NULL;
   return pub_k;
}

/** Get the private key, but remove it from the key pair storage, so it is not
 * deleted and freed along with this class.
 * 
 * @return
 * A pointer to the RSAPrivateKey of the generated pair. By calling this, the
 * key is removed from this generator instance, and the responsibility to
 * delete the key now rests with the caller. Subsequent calls will return
 * NULL. */
RSAPrivateKey *RSAKeyPairGenerator::popPrivateKey()
{
   RSAPrivateKey *prv_k = prv;
   prv = NULL;
   return prv_k;
}
